//
//  component_container
//  Created by tom on 2022/4/26.
//  Copyright ©xcar. All rights reserved.
//

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:logger/logger.dart';

export 'package:flutter_screenutil/flutter_screenutil.dart';
export 'package:logger/logger.dart';

/// 全局日志实例
final Logger logger = Logger();

class DYComponentContainer extends StatelessWidget {
  final Map<String, dynamic> data;
  final Widget child;

  const DYComponentContainer({Key? key, required this.data, required this.child});

  @override
  Widget build(BuildContext context) {
    final double left = ComponentValue.doubleInfoValueForUIKey(data, 'padding_left');
    final double right =
    ComponentValue.doubleInfoValueForUIKey(data, 'padding_right');
    final double top = ComponentValue.doubleInfoValueForUIKey(data, 'padding_top');
    final double bottom =
    ComponentValue.doubleInfoValueForUIKey(data, 'padding_bottom');
    double height = ComponentValue.doubleInfoValueForUIKey(data, 'height',
        defaultValue: -1);
    double width =
    ComponentValue.doubleInfoValueForUIKey(data, 'width', defaultValue: -1);
    final double minHeight = ComponentValue.doubleInfoValueForUIKey(data, 'min_height',
        defaultValue: -1);
    final double minWidth =
    ComponentValue.doubleInfoValueForUIKey(data, 'min_width', defaultValue: -1);
    if (width > 0 && minWidth > 0) {
      width = width > minWidth ? width : minWidth;
    }
    if (height > 0 && minHeight > 0) {
      height = height > minHeight ? height : minHeight;
    }

    final Color color = ColorExt.colorFromString(
        ComponentValue.stringInfoValueForUIKey(data, 'color'),
        defaultColor: ColorExt.randomColor);

    if (width > 0) {
      if (height > 0) {
        return Container(
          alignment: Alignment.center,
          padding: EdgeInsets.only(
              left: left, top: top, right: right, bottom: bottom),
          color: color,
          height: height,
          width: width,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: 0,
                bottom: 0,
                left: 0,
                right: 0,
                child: child,
              ),
            ],
          ),
        );
      } else {
        return Container(
          alignment: Alignment.center,
          padding: EdgeInsets.only(
              left: left, top: top, right: right, bottom: bottom),
          color: color,
          width: width,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: 0,
                bottom: 0,
                left: 0,
                right: 0,
                child: child,
              ),
            ],
          ),
        );
      }
    } else {
      if (height > 0) {
        return Container(
          alignment: Alignment.center,
          padding: EdgeInsets.only(
              left: left, top: top, right: right, bottom: bottom),
          color: color,
          height: height,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: 0,
                bottom: 0,
                left: 0,
                right: 0,
                child: child,
              ),
            ],
          ),
        );
      } else {
        return Container(
          alignment: Alignment.center,
          padding: EdgeInsets.only(
              left: left, top: top, right: right, bottom: bottom),
          color: color,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: 0,
                bottom: 0,
                left: 0,
                right: 0,
                child: child,
              ),
            ],
          ),
        );
      }
    }
  }
}

class ComponentValue {
  /// 直接获取info中的value
  static dynamic infoValueForKey(Map<String, dynamic> componentJson, String key) {
    final Map<String, dynamic> infoData = componentJson.mapForKey('info');
    return infoData.valueForKey(key);
  }

  /// 根据ui中的key，获取info中的value
  static dynamic infoValueForUIKey(Map<String, dynamic> componentJson, String uiKey) {
    final Map<String, dynamic> infoData = componentJson.mapForKey('info');
    final Map<String, dynamic> uiData = componentJson.mapForKey('ui');

    dynamic uiValue = uiData.valueForKey(uiKey);
    if (uiValue is String && uiValue.startsWith('info.')) {
      final String replaceKey = uiValue.replaceFirst('info.', '');
      uiValue = infoData.valueForKey(replaceKey);
    } else if (uiData.containsKey(uiKey) == false && infoData.containsKey(uiKey)) {
      uiValue = infoData.valueForKey(uiKey);
    }
    return uiValue;
  }

  static String stringInfoValueForUIKey(Map<String, dynamic> componentJson, String uiKey,
      {String defaultValue = ''}) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    return value == null
        ? defaultValue
        : (value is String ? value : defaultValue);
  }

  static List<dynamic> listInfoValueForUIKey(Map<String, dynamic> componentJson, String uiKey) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    return value == null ? <dynamic>[] : (value is List ? value : <dynamic>[]);
  }

  static List<Map<String, dynamic>> listMapInfoValueForUIKey(
      Map<String, dynamic> componentJson, String uiKey) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    return value == null ? <Map<String, dynamic>>[] : (value is List<Map<String, dynamic>> ? value : <Map<String, dynamic>>[]);
  }

  static bool boolInfoValueForUIKey(Map<String, dynamic> componentJson, String uiKey) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    return value == null
        ? false
        : (value is bool ? value : (value is int && value > 0));
  }

  static int intInfoValueForUIKey(Map<String, dynamic> componentJson, String uiKey) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    return value == null
        ? 0
        : (value is int
        ? value
        : (value is String ? int.tryParse(value) ?? 0 : 0));
  }

  static double doubleInfoValueForUIKey(Map<String, dynamic> componentJson, String uiKey, {double defaultValue = 0}) {
    final dynamic value = infoValueForUIKey(componentJson, uiKey);
    if (value == null) {
      return defaultValue;
    }
    if (value is int) {
      return value.toDouble();
    }
    if (value is String) {
      if (value.endsWith('.w')) {
        return (double.tryParse(value.replaceAll('.w', '')) ?? defaultValue).w;
      } else if (value.endsWith('.h')) {
        return (double.tryParse(value.replaceAll('.h', '')) ?? defaultValue).h;
      } else if (value.endsWith('sw')) {
        return (double.tryParse(value.replaceAll('sw', '')) ?? defaultValue) * ScreenUtil().screenWidth;
      } else if (value.endsWith('sh')) {
        return (double.tryParse(value.replaceAll('sh', '')) ?? defaultValue) * ScreenUtil().screenHeight;
      }
      return double.tryParse(value) ?? defaultValue;
    }
    return defaultValue;
  }
}

/// Map<String, dynamic> Extension
extension MapExt on Map<String, dynamic> {
  Map<String, dynamic> copy() {
    return Map<String, dynamic>.of(this);
  }

  void setValueForKey(dynamic value, {required String key}) {
    if (key.isEmpty) {
      return;
    }
    this[key] = value;
  }

  dynamic valueForKey(String key) {
    if (containsKey(key)) {
      return this[key];
    }
    return null;
  }

  Map<String, dynamic> mapForKey(String key) {
    if (containsKey(key)) {
      final dynamic value = this[key];
      if (value != null) {
        if (value is Map<String, dynamic>) {
          return value;
        }
        logger.e('map $this, key $key, value is not Map, value: $value');
      }
      return <String, dynamic>{};
    }
    return <String, dynamic>{};
  }

  bool boolForKey(String key, {bool defaultValue = false}) {
    if (containsKey(key)) {
      final dynamic value = this[key];
      if (value != null) {
        if (value is bool) {
          return value;
        } else if (value is int && value >= 1) {
          return true;
        }
      }
    }
    return defaultValue;
  }

  int intForKey(String key, {int defaultValue = 0}) {
    if (containsKey(key)) {
      final dynamic value = this[key];
      if (value != null) {
        if (value is int) {
          return value;
        } else if (value is String) {
          return int.tryParse(value) ?? 0;
        }
      }
    }
    return defaultValue;
  }

  double doubleForKey(String key, {double defaultValue = 0}) {
    if (containsKey(key)) {
      final dynamic value = this[key];
      if (value != null) {
        if (value is int) {
          return value.toDouble();
        } else if (value is double) {
          return value;
        } else if (value is String) {
          if (value.endsWith('.w')) {
            return (double.tryParse(value.replaceAll('.w', '')) ?? 0.0).w;
          } else if (value.endsWith('.h')) {
            return (double.tryParse(value.replaceAll('.h', '')) ?? 0.0).h;
          } else if (value.endsWith('sw')) {
            return (double.tryParse(value.replaceAll('sw', '')) ?? 0.0) * ScreenUtil().screenWidth;
          } else if (value.endsWith('sh')) {
            return (double.tryParse(value.replaceAll('sh', '')) ?? 0.0) * ScreenUtil().screenHeight;
          }
          return double.tryParse(value) ?? 0.0;
        }
      }
    }
    return defaultValue;
  }

  String stringForKey(String key, {String defaultValue = ''}) {
    if (containsKey(key)) {
      final dynamic value = this[key];
      if (value != null) {
        if (value is String) {
          if (value.isEmpty && defaultValue.isNotEmpty) {
            return defaultValue;
          }
          return value;
        } else if (value is int || value is double) {
          return value.toString();
        }
      }
    }
    return '';
  }

  Map<String, dynamic> replaceForKey(
      String key, Map<String, dynamic> newSubMap) {
    if (containsKey(key)) {
      remove(key);
      if (newSubMap.isNotEmpty) {
        addAll(newSubMap);
      }
    }
    return this;
  }

  Map<String, dynamic> replaceKeyWithNewKey(String key, String newKey) {
    if (newKey.isEmpty) {
      return this;
    }
    if (containsKey(key)) {
      final dynamic value = this[key];
      remove(key);
      this[newKey] = value;
      return this;
    }
    return this;
  }
}


Map<String, Color> colorMap = <String, Color>{
  'lightBlue': Colors.lightBlue,
  'pinkAccent': Colors.pinkAccent,
  'red': Colors.red,
  'green': Colors.green,
  'blue': Colors.blue,
  'white': Colors.white,
  'yellow': Colors.yellow,
};

/// Color Extension
extension ColorExt on Color {
  /// random color
  static Color get randomColor {
    return Color.fromRGBO(
        Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1);
  }

  static Color colorFromString(String colorString,
      {Color defaultColor = Colors.white}) {
    if (colorString.isEmpty) {
      return defaultColor;
    }
    if (colorMap.containsKey(colorString)) {
      return colorMap[colorString]!;
    } else {
      final int colorInt = hexFromColor(colorString);
      if (colorInt == -1) {
        return defaultColor;
      }
      return Color(colorInt);
    }
  }

  /// Color from HexString
  static Color colorFromHexString(String hexString,
      {Color defaultColor = Colors.white}) {
    final int colorInt = hexFromColor(hexString);
    if (colorInt == -1) {
      return defaultColor;
    }
    return Color(colorInt);
  }

  static int hexFromColor(String hexColor) {
    if (hexColor.isEmpty) {
      return -1;
    }
    hexColor = hexColor.toUpperCase().replaceAll('#', '');
    hexColor = hexColor.replaceAll('0X', '');
    if (hexColor.length == 6) {
      hexColor = 'FF' + hexColor;
    }
    return int.tryParse(hexColor, radix: 16) ?? -1;
  }
}